// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Components/GameFrameworkComponent.h"

#include "LyraHealthComponent.generated.h"

class ULyraHealthComponent;

class ULyraAbilitySystemComponent;
class ULyraHealthSet;
class UObject;
struct FFrame;
struct FGameplayEffectSpec;
struct FOnAttributeChangeData;

// 声明一个动态多播委托，当死亡事件发生时调用，参数为拥有者Actor
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLyraHealth_DeathEvent, AActor*, OwningActor);
// 声明一个动态多播委托，当属性值改变时调用，参数为健康组件、旧值、新值和触发者
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FLyraHealth_AttributeChanged, ULyraHealthComponent*, HealthComponent, float, OldValue, float, NewValue, AActor*, Instigator);

/**
 * ELyraDeathState
 *
 *	定义当前的死亡状态。
 */
UENUM(BlueprintType)
enum class ELyraDeathState : uint8
{
	NotDead = 0,        // 未死亡
	DeathStarted,       // 死亡开始
	DeathFinished       // 死亡结束
};

/**
 * ULyraHealthComponent
 *
 *	用于处理与生命值相关的所有功能的Actor组件。
 */
UCLASS(Blueprintable, Meta=(BlueprintSpawnableComponent))
class LYRAGAME_API ULyraHealthComponent : public UGameFrameworkComponent
{
	GENERATED_BODY()

public:
	// 构造函数
	ULyraHealthComponent(const FObjectInitializer& ObjectInitializer);

	// 如果指定Actor上存在健康组件，则返回该组件
	UFUNCTION(BlueprintPure, Category = "Lyra|Health")
	static ULyraHealthComponent* FindHealthComponent(const AActor* Actor) { return (Actor ? Actor->FindComponentByClass<ULyraHealthComponent>() : nullptr); }

	// 使用能力系统组件初始化该组件
	UFUNCTION(BlueprintCallable, Category = "Lyra|Health")
	void InitializeWithAbilitySystem(ULyraAbilitySystemComponent* InASC);

	// 取消初始化组件，清除对能力系统的任何引用
	UFUNCTION(BlueprintCallable, Category = "Lyra|Health")
	void UninitializeFromAbilitySystem();

	// 返回当前生命值
	UFUNCTION(BlueprintCallable, Category = "Lyra|Health")
	float GetHealth() const;

	// 返回当前最大生命值
	UFUNCTION(BlueprintCallable, Category = "Lyra|Health")
	float GetMaxHealth() const;

	// 返回当前生命值的归一化值，范围[0.0, 1.0]
	UFUNCTION(BlueprintCallable, Category = "Lyra|Health")
	float GetHealthNormalized() const;

	// 返回当前死亡状态
	UFUNCTION(BlueprintCallable, Category = "Lyra|Health")
	ELyraDeathState GetDeathState() const { return DeathState; }

	// 检查是否已死亡或正在死亡
	UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Lyra|Health", Meta = (ExpandBoolAsExecs = "ReturnValue"))
	bool IsDeadOrDying() const { return (DeathState > ELyraDeathState::NotDead); }

	// 开始拥有者的死亡序列
	virtual void StartDeath();

	// 结束拥有者的死亡序列
	virtual void FinishDeath();

	// 施加足够伤害来杀死拥有者（自毁）
	virtual void DamageSelfDestruct(bool bFellOutOfWorld = false);

public:
	// 当生命值改变时触发的委托
	UPROPERTY(BlueprintAssignable)
	FLyraHealth_AttributeChanged OnHealthChanged;

	// 当最大生命值改变时触发的委托
	UPROPERTY(BlueprintAssignable)
	FLyraHealth_AttributeChanged OnMaxHealthChanged;

	// 当死亡序列开始时触发的委托
	UPROPERTY(BlueprintAssignable)
	FLyraHealth_DeathEvent OnDeathStarted;

	// 当死亡序列结束时触发的委托
	UPROPERTY(BlueprintAssignable)
	FLyraHealth_DeathEvent OnDeathFinished;

protected:
	// 组件取消注册时的重写函数
	virtual void OnUnregister() override;

	// 清除游戏标签
	void ClearGameplayTags();

	// 处理生命值改变的回调函数
	virtual void HandleHealthChanged(const FOnAttributeChangeData& ChangeData);
	// 处理最大生命值改变的回调函数
	virtual void HandleMaxHealthChanged(const FOnAttributeChangeData& ChangeData);
	// 处理生命值耗尽时的回调函数
	virtual void HandleOutOfHealth(AActor* DamageInstigator, AActor* DamageCauser, const FGameplayEffectSpec& DamageEffectSpec, float DamageMagnitude);

	// 死亡状态复制时的回调函数
	UFUNCTION()
	virtual void OnRep_DeathState(ELyraDeathState OldDeathState);

protected:
	// 该组件使用的能力系统
	UPROPERTY()
	TObjectPtr<ULyraAbilitySystemComponent> AbilitySystemComponent;

	// 该组件使用的生命值属性集
	UPROPERTY()
	TObjectPtr<const ULyraHealthSet> HealthSet;

	// 用于处理死亡的复制状态
	UPROPERTY(ReplicatedUsing = OnRep_DeathState)
	ELyraDeathState DeathState;
};